package com.gopay.bis.service.bank.impl;

import com.gopay.bis.common.util.BisPayCheckUtils;
import com.gopay.bis.common.util.constants.BisPayConstants;
import com.gopay.bis.manager.bank.external.BisPayMessageManager;
import com.gopay.bis.manager.bank.payconfig.BisBankExtConfigManager;
import com.gopay.bis.service.bank.BankOrderService;
import com.gopay.bis.service.bank.external.BisExternalPlatformService;
import com.gopay.common.Result;
import com.gopay.common.constants.bank.BankOrderType;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.bank.BisBankInterfaceChannel;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BankOrder;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.external.BisBankMerchant;
import com.gopay.common.domain.bank.external.BisExternalMessage;
import com.gopay.common.domain.bank.external.BisPayMessage;
import com.gopay.common.domain.bis.BaseBisBankExtConfig;
import com.gopay.common.exception.GopayException;
import com.gopay.common.order.bankorder.trade.InitialSpringBeanName;
import com.gopay.common.order.bankorder.trade.TradeType;
import com.gopay.common.util.HttpsTransport;
import com.gopay.common.util.spring.SpringContextUtil;
import com.gopay.remote.bank.BankInteractRemoteService;
import com.gopay.remote.bank.BisInteractRemoteService;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * BIS对外接口
 * 
 * @BisExternalServiceImpl.java
 * @author wanggang
 */
@Service("bisInteractExternalService")
public class BisInteractExternalServiceImpl implements BankInteractRemoteService {

    private static Logger logger = LoggerFactory.getLogger(BisInteractExternalServiceImpl.class);

    @Resource(name = "bankOrderService")
    private BankOrderService bankOrderService;
    
    @Resource(name = "bisExternalService")
    private BisInteractRemoteService bisExternalService;
   
    @Resource(name = "bisExternalPlatformService")
    private BisExternalPlatformService bisExternalPlatformService;
    
	@Resource(name = "bisBankExtConfigManager")
	BisBankExtConfigManager bisBankExtConfigManager;
    
	@Resource(name = "bisPayMessageManager")
	BisPayMessageManager bisPayMessageManager;

    
    @Override
    public Result pay(BaseMessage base) {
        logger.error("BisInteractExternalServiceImpl银行支付处理base对象：" + ToStringBuilder.reflectionToString(base));
        Result result = new Result();
        try {
        	//进行验签校验
        	boolean verifyRes = bisExternalService.pay(base);
            BisExternalMessage message = (BisExternalMessage) base;
        	if(verifyRes){
        		BisPayMessage bisPayMessage = bisExternalPlatformService.saveBisPayMessage(message);
                message.setOrderId(bisPayMessage.getGopayOrderId());
                message.setBankOrderId(bisPayMessage.getGopayOrderId());
        	}else{
        		throw new GopayException(ProcCodeConstants.PROC_CODE_100E1142);
        	}
            // 获取SPRING加载的BeanName
            String beanName = getBeanName(message);
            BankInteractRemoteService bankService = (BankInteractRemoteService) SpringContextUtil.getBean(beanName);
            BaseBisBankExtConfig bankConfig = bisBankExtConfigManager.findExtConfigByBankCodeAndBankBusProd(base.getBankBusProd(), base.getBank());
            //如果需要使用新生自己的证书
            if(message.getIsThroughBis().equals("1")){
            	BisBankMerchant bisBankMerchant = bisExternalPlatformService.getBankMerchant(message.getPlatformID(), message.getBank(), message.getBankBusProd().value);
            	//设置商户号
                message.setMerID(bisBankMerchant.getIntrMernum1());
    			//设置二级商户号
                message.setMerID2nd(bisBankMerchant.getIntrMernum2());
    			//设置结算账户网点联行号
                message.setBranchCode(bisBankMerchant.getBranchCode());
                //设置一级私钥路劲
                message.setPrivateKeyPath(bisBankMerchant.getIntrMerPravkeyPath());
                //设置一级私钥密码
                message.setPrivatePwd(bisBankMerchant.getIntrMerPravkeyPwd());
    			//设置二级私钥路径
                message.setPrivateKeyPath2nd(bisBankMerchant.getIntrMer2ndPravkeyPath());
    			//设置二级私钥密码
                message.setPrivatePwd2nd(bisBankMerchant.getIntrMer2ndPravkeyPwd());
                //设置公钥路径
                message.setPublicKeyPath(bisBankMerchant.getIntrBankPubkeyPath());
            }else{
    			//设置商户号
    			message.setMerID(bankConfig.getIntrMernum1());
    			//设置二级商户号
    			message.setMerID2nd(bankConfig.getIntrMernum2());    			
    			//设置结算账户网点联行号
                message.setBranchCode(bankConfig.getBranchCode());
    			//设置一级私钥路径
                message.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
    			//设置一级私钥密码
                message.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
    			//设置二级私钥路径
                message.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
    			//设置二级私钥密码
                message.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
    			//设置公钥路径
    			message.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
            }
			//设置银行查询地址
			message.setPayUrl(bankConfig.getPayUrl());
			//设置支付后台通知地址
			message.setPayRuturnUrl(bankConfig.getPayRuturnUrl());
			//设置支付后前通知地址
			message.setPayNotifyUrl(bankConfig.getPayNotifyUrl());
            result = bankService.pay(message);
            BaseMessage baseMessage = (BaseMessage) result.getDefaultModel();
            logger.error("BisInteractExternalServiceImpl银行支付签名返回处理base对象：" + ToStringBuilder.reflectionToString(baseMessage));
            // 校验银行订单不能为多条
            List<BankOrder> bankOrders = bankOrderService.getBankOrdersByGopayOrderId(base.getOrderId());
            if (bankOrders != null && bankOrders.size() > 0) {
                result.setResultCode(ProcCodeConstants.PROC_CODE_100E5015);// 已存在相同的订单
                result.setSuccess(false);
                return result;
            }
            // 新增bankOrder info
            if(BisPayConstants.GOPAY_PLATFORMID.equals(message.getPlatformID())){
            	baseMessage.setBankOrderType(BankOrderType.GOPAY_BPS_ORDER);//订单类型：BPS订单
            }else if(BisPayConstants.IS_THROUGH_BIS_YES.equals(message.getIsThroughBis())) {
            	baseMessage.setBankOrderType(BankOrderType.THIRDPARTY_PLATFORM);//订单类型：第三方国付宝通道订单
            }else if(BisPayConstants.IS_THROUGH_BIS_NO.equals(message.getIsThroughBis())) {
            	baseMessage.setBankOrderType(BankOrderType.INDEPENDENT_MERCHANTS);//订单类型：第三方平台独立通道订单
            }
            bankOrderService.addBankOrder(baseMessage);
        } catch (GopayException e) {
            logger.error("BisInteractExternalServiceImpl pay error: ", e);
            result.setResultCode(e.getErrCode());
            result.setSuccess(false);
        } catch (Exception e) {
            logger.error("BisInteractExternalServiceImpl pay error: ", e);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
            result.setSuccess(false);
        }
        return result;
    }

    @Override
    public Result bankBack(BaseMessage base) {
    	//进行验签校验
    	Result result = new Result();
    	try {
    		BisExternalMessage message = (BisExternalMessage) base;
    		//获取外部订单交易对象
			BisPayMessage bisPayMessage = bisPayMessageManager.getBisPayMessageByGopayOrderId(base.getOrderId());
			List<BankOrder> bankOrders = bankOrderService.getBankOrdersByGopayOrderId(base.getOrderId());
			message.setBankOrderId(bankOrders.get(0).getOutOrderId());
			message.setOutOrderId(bisPayMessage.getPlatformOrderId());
			message.setPlatformID(bisPayMessage.getPlatformId());
			message.setReturnUrl(bisPayMessage.getReturnUrl());
        	//签名
    		message = bisExternalService.bankBack(message);
    		//通知外部平台
			Map<String, String> param = new HashMap<String, String>();
			param.put("isThroughBis", message.getIsThroughBis());
			param.put("platformID", message.getPlatformID());
			param.put("signType", message.getSignType());
			param.put("sign", message.getSignMessage());
			param.put("orderID", bisPayMessage.getPlatformOrderId());
			//如果是BPS订单则设置发往银行订单号
			if(BisPayCheckUtils.checkGoPayOrderID(message.getOrderId())){
				param.put("bisBankOrderID", bankOrders.get(0).getOutOrderId());
			}
			param.put("platformDate", message.getPlatformDate());
			param.put("bank", message.getBank());
			param.put("amount", message.getAmount().toString());
			param.put("amountType", message.getAmountType());
			param.put("tradeType", Integer.toString(message.getTradeType()));
			param.put("tradeState", message.getTradeState());		
			HttpsTransport httpsTransport = new HttpsTransport();
    		httpsTransport.setUrl(message.getReturnUrl());
    		httpsTransport.setTimeout(30000);
    		logger.error("bisInteractExternalService银行返回处理发送参数："+ToStringBuilder.reflectionToString(param));
    		Object redirectUrl = httpsTransport.submit(param);
    		result.setDefaultModel(message);
    		result.setModel("redirectUrl", redirectUrl);
    		result.setSuccess(true);
        } catch (GopayException e) {
            logger.error("BankInteractServiceImpl bankBack error: ", e);
            result.setResultCode(e.getErrCode());
            result.setSuccess(false);
        } catch (Exception e) {
            logger.error("BankInteractServiceImpl bankBack error: ", e);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
            result.setSuccess(false);
        }
        return result;
    }
    
    @Override
    public Result query(BaseMessage base) {
        logger.error("BisInteractExternalServiceImpl银行查询处理base对象：" + ToStringBuilder.reflectionToString(base));
        Result result = new Result();
        try {
        	//进行验签校验
        	boolean veryfyRequest = bisExternalService.queryBack(base);    
        	if(!veryfyRequest){//验签不通过
        		throw new GopayException(ProcCodeConstants.PROC_CODE_100E1142);
        	}
            BisExternalMessage message = (BisExternalMessage) base;
            // 获取SPRING加载的BeanName
            String beanName;
            // 读取发往银行信息
            List<BankOrder> bankOrders = bankOrderService.getBankOrdersByGopayOrderId(message.getOrderId());
            if (bankOrders != null && bankOrders.size() > 0) {
            	String beanSuffix="",outStlmCd,bankBizProdCode;
            	outStlmCd = InitialSpringBeanName.getOutStlmCd(bankOrders.get(0).getInterfaceChennelCode(), bankOrders.get(0).getBankBizProdCode(), bankOrders.get(0).getBankCode());
            	message.setBank(bankOrders.get(0).getBankCode());
            	message.setOutStlmCd(outStlmCd);
            	message.setBankOrderId(bankOrders.get(0).getOutOrderId());
            	message.setOrderId(bankOrders.get(0).getOrderId());
            	message.setBankOrderId(bankOrders.get(0).getOutOrderId());
            	message.setBankIntrChann(BisBankInterfaceChannel.get(bankOrders.get(0).getInterfaceChennelCode()));
            	bankBizProdCode = bankOrders.get(0).getBankBizProdCode();
            	if(BisBankBusinessProd._00.value.equals(bankBizProdCode)){
            		beanSuffix = "B2C";
            		message.setBankBusProd(BisBankBusinessProd._00);
            	}else if(BisBankBusinessProd._01.value.equals(bankBizProdCode)){
            		beanSuffix = "B2B";
            		message.setBankBusProd(BisBankBusinessProd._01);
                }else if(BisBankBusinessProd._11.value.equals(bankBizProdCode)){
                    beanSuffix = "B2C";
                    message.setBankBusProd(BisBankBusinessProd._00);
            	}else{
                	throw new GopayException(ProcCodeConstants.PROC_CODE_100E1141);
                }
            	beanName = outStlmCd+"-"+beanSuffix;
            }else{
            	throw new GopayException(ProcCodeConstants.PROC_CODE_100E1141);
            }
            BankInteractRemoteService bankService = (BankInteractRemoteService) SpringContextUtil.getBean(beanName);
            BaseBisBankExtConfig bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(message.getBankBusProd(), message.getBankIntrChann(), message.getBank());
            //如果需要使用新生自己的证书
            if(message.getIsThroughBis().equals("1")){
            	BisBankMerchant bisBankMerchant = bisExternalPlatformService.getBankMerchant(message.getPlatformID(), message.getBank(), message.getBankBusProd().value);
            	//设置商户号
                message.setMerID(bisBankMerchant.getIntrMernum1());
    			//设置二级商户号
                message.setMerID2nd(bisBankMerchant.getIntrMernum2());                
    			//设置结算账户网点联行号
                message.setBranchCode(bisBankMerchant.getBranchCode());   
                //设置一级私钥路劲
                message.setPrivateKeyPath(bisBankMerchant.getIntrMerPravkeyPath());
                //设置一级私钥密码
                message.setPrivatePwd(bisBankMerchant.getIntrMerPravkeyPwd());
    			//设置二级私钥路径
                message.setPrivateKeyPath2nd(bisBankMerchant.getIntrMer2ndPravkeyPath());
    			//设置二级私钥密码
                message.setPrivatePwd2nd(bisBankMerchant.getIntrMer2ndPravkeyPwd());             
                //设置公钥路径
                message.setPublicKeyPath(bisBankMerchant.getIntrBankPubkeyPath());
            }else{
    			//设置商户号
    			message.setMerID(bankConfig.getIntrMernum1());
    			//设置二级商户号
    			message.setMerID2nd(bankConfig.getIntrMernum2());     			
    			//设置结算账户网点联行号
                message.setBranchCode(bankConfig.getBranchCode());
    			//设置一级私钥路径
                message.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
    			//设置一级私钥密码
                message.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
    			//设置二级私钥路径
                message.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
    			//设置二级私钥密码
                message.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
    			//设置公钥路径
    			message.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
            }
			//设置银行支付地址
			message.setQueryUrl(bankConfig.getQueryUrl());			
			//设置支付后台通知地址
			message.setPayRuturnUrl(bankConfig.getPayRuturnUrl());
			//设置支付后前通知地址
			message.setPayNotifyUrl(bankConfig.getPayNotifyUrl());
            result = bankService.query(message);
            if(result.isSuccess()){//查询成功
				Map<String, String> param  = (Map<String, String>) result.getModel("queryResult");
				String returnCode = param.get("returnCode");
				String returnMessage = param.get("returnMessage");
				String tradeState = param.get("tradeState");
				message.setReturnCode(returnCode);
				message.setReturnMessage(returnMessage);
				message.setTradeState(tradeState);
            }
            //更新主订单表状态
            if(message.getTradeState().equals("1")){
            	bankOrderService.updateBpsSuccess(message.getOrderId());
            }else if(message.getTradeState().equals("-1")){
            	bankOrderService.updateBpsFail(message.getOrderId());
            }else if(message.getTradeState().equals("0")){
            	bankOrderService.updateBpsOther(message.getOrderId());
            }
            logger.error("BankInteractServiceImpl银行查询返回base对象："+ToStringBuilder.reflectionToString(result));
            String sign = bisExternalService.querySubmit(message); 
            result.setDefaultModel(sign);
            result.setSuccess(true);
        } catch (GopayException e) {
            logger.error("BankInteractServiceImpl query error: ", e);
            result.setResultCode(e.getErrCode());
            result.setSuccess(false);
        } catch (Exception e) {
            logger.error("BankInteractServiceImpl query error: ", e);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
            result.setSuccess(false);
        }
        return result;
    }

    /**
     * 获取SPRING加载的BeanName
     * 
     * <pre>
     * BeanName规范:银行编码-交易类型，如TBANK-B2B
     * </pre>
     * 
     * @param mainOrder
     *            订单信息
     * @param bankInfo
     *            银行信息
     * @return
     * @throws GopayException
     */
    private String getBeanName(BaseMessage base) throws GopayException {
        BisExternalMessage bisMessage = (BisExternalMessage) base;
        String beanSuffix = "";
        if (BisPayConstants.TRADETYPE_B2B.equals(String.valueOf(bisMessage.getTradeType()))) {
            beanSuffix = "B2B";
        } else if (BisPayConstants.TRADETYPE_B2C.equals(String.valueOf(bisMessage.getTradeType()))) {
            beanSuffix = "B2C";
        }
        String outStlmId = "";
        if (BisPayConstants.IS_THROUGH_BIS_YES.equals(bisMessage.getIsThroughBis())) {
            if (StringUtils.equals(TradeType.TRADE_TYPE_B2C, beanSuffix)) {
                outStlmId = InitialSpringBeanName.getOutStlmCd(bisMessage.getBankIntrChann().value,
                        bisMessage.getBankBusProd().value, bisMessage.getBank());
            } else {
                outStlmId = bisMessage.getBank();
            }
        } else if (BisPayConstants.IS_THROUGH_BIS_NO.equals(bisMessage.getIsThroughBis())) {
            outStlmId = bisMessage.getBank();
        }
        return outStlmId + "-" + beanSuffix;
    }

    @Override
    public Result refund(BaseMessage base) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Result dayend(BaseMessage base) {
        // TODO Auto-generated method stub
        return null;
    }

	@Override
	public Result queryBack(BaseMessage base) {
		// TODO Auto-generated method stub
		return null;
	}

    @Override
    public Result refundBack(BaseMessage base) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Result refundQuery(BaseMessage base) {
        // TODO Auto-generated method stub
        return null;
    }

	@Override
	public Result sendBankRefund(BaseMessage base) {
		// TODO Auto-generated method stub
		return null;
	}
}
